package com.yu1996.gulimall.product.service.impl;

import com.yu1996.common.constant.ProductConstant;
import com.yu1996.common.constant.ProductConstant.StatusEnum;
import com.yu1996.common.to.SkuReductionTo;
import com.yu1996.common.to.SpuBoundTo;
import com.yu1996.common.to.es.SkuEsModel;
import com.yu1996.common.utils.R;
import com.yu1996.gulimall.product.entity.AttrEntity;
import com.yu1996.gulimall.product.entity.BrandEntity;
import com.yu1996.gulimall.product.entity.CategoryEntity;
import com.yu1996.gulimall.product.entity.ProductAttrValueEntity;
import com.yu1996.gulimall.product.entity.SkuImagesEntity;
import com.yu1996.gulimall.product.entity.SkuInfoEntity;
import com.yu1996.gulimall.product.entity.SkuSaleAttrValueEntity;
import com.yu1996.gulimall.product.entity.SpuImagesEntity;
import com.yu1996.gulimall.product.entity.SpuInfoDescEntity;
import com.yu1996.gulimall.product.feign.CouponFeignService;
import com.yu1996.gulimall.product.feign.SearchFeignService;
import com.yu1996.gulimall.product.feign.WareFeignService;
import com.yu1996.gulimall.product.service.AttrService;
import com.yu1996.gulimall.product.service.BrandService;
import com.yu1996.gulimall.product.service.CategoryService;
import com.yu1996.gulimall.product.service.ProductAttrValueService;
import com.yu1996.gulimall.product.service.SkuImagesService;
import com.yu1996.gulimall.product.service.SkuInfoService;
import com.yu1996.gulimall.product.service.SkuSaleAttrValueService;
import com.yu1996.gulimall.product.service.SpuImagesService;
import com.yu1996.gulimall.product.service.SpuInfoDescService;
import com.yu1996.gulimall.product.vo.Attr;
import com.yu1996.gulimall.product.vo.Bounds;
import com.yu1996.gulimall.product.vo.Images;
import com.yu1996.gulimall.product.vo.Skus;
import com.yu1996.gulimall.product.vo.SpuSaveVo;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yu1996.common.utils.PageUtils;
import com.yu1996.common.utils.Query;

import com.yu1996.gulimall.product.dao.SpuInfoDao;
import com.yu1996.gulimall.product.entity.SpuInfoEntity;
import com.yu1996.gulimall.product.service.SpuInfoService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@Slf4j
@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity>
    implements SpuInfoService {

  @Autowired private SpuInfoDescService spuInfoDescService;
  @Autowired private SpuImagesService spuImagesService;
  @Autowired private ProductAttrValueService productAttrValueService;
  @Autowired private SkuInfoService skuInfoService;
  @Autowired private SkuImagesService skuImagesService;
  @Autowired private SkuSaleAttrValueService skuSaleAttrValueService;
  @Autowired private CouponFeignService couponFeignService;
  @Autowired private SearchFeignService searchFeignService;
  @Autowired private WareFeignService wareFeignService;
  @Autowired private AttrService attrService;
  @Autowired private BrandService brandService;
  @Autowired private CategoryService categoryService;

  @Override
  public PageUtils queryPage(Map<String, Object> params) {
    IPage<SpuInfoEntity> page =
        this.page(new Query<SpuInfoEntity>().getPage(params), new QueryWrapper<SpuInfoEntity>());

    return new PageUtils(page);
  }

  @Transactional
  @Override
  public void saveSpuInfo(SpuSaveVo vo) {
    // 1、保存spu的基本信息；pms_spu_info
    SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
    BeanUtils.copyProperties(vo, spuInfoEntity);
    spuInfoEntity.setCreateTime(new Date());
    spuInfoEntity.setUpdateTime(new Date());
    this.baseMapper.insert(spuInfoEntity);
    // 2、保存spu的描述；pms_spu_info_desc
    List<String> decript = vo.getDecript();
    SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
    spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
    spuInfoDescEntity.setDecript(String.join(",", decript));
    spuInfoDescService.save(spuInfoDescEntity);
    // 3、保存spu的图片集；pms_spu_images
    spuImagesService.saveImages(spuInfoEntity.getId(), vo.getImages());
    // 4、保存spu的规格参数；pms_product_attr_value
    productAttrValueService.saveAttrs(spuInfoEntity.getId(), vo.getBaseAttrs());
    // 5、保存spu的积分信息；gulimall_sms =》》sms_spu_bounds
    Bounds bounds = vo.getBounds();
    SpuBoundTo spuBoundTo = new SpuBoundTo();
    BeanUtils.copyProperties(bounds, spuBoundTo);
    spuBoundTo.setSpuId(spuInfoEntity.getId());
    R r = couponFeignService.saveSpuBounds(spuBoundTo);
    if (r.getCode() != 0) {
      log.error("远程保存spu积分信息失败");
    }
    // 6、保存spu对应的sku信息

    List<Skus> skus = vo.getSkus();
    if (skus != null && skus.size() > 0) {
      skus.forEach(
          item -> {
            String defaultImg = "";
            for (Images image : item.getImages()) {
              if (image.getDefaultImg() == 1) {
                defaultImg = image.getImgUrl();
              }
            }
            // 6.1 sku的基本信息；pms_sku_info
            SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
            BeanUtils.copyProperties(item, skuInfoEntity);
            skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
            skuInfoEntity.setSkuId(spuInfoEntity.getId());
            skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
            skuInfoEntity.setSaleCount(0L);
            skuInfoEntity.setSkuDefaultImg(defaultImg);
            skuInfoService.save(skuInfoEntity);
            // 6.2 sku的图片信息；pms_sku_images
            List<Images> images = item.getImages();
            if (images != null && images.size() > 0) {
              List<SkuImagesEntity> collect =
                  images.stream()
                      .map(
                          image -> {
                            SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                            skuImagesEntity.setSkuId(spuInfoEntity.getId());
                            skuImagesEntity.setDefaultImg(image.getDefaultImg());
                            skuImagesEntity.setImgUrl(image.getImgUrl());
                            return skuImagesEntity;
                          })
                      .filter(
                          itemImage -> {
                            return !StringUtils.isEmpty(itemImage.getImgUrl());
                          })
                      .collect(Collectors.toList());
              skuImagesService.saveBatch(collect);
            }
            // 6.3 sku的销售属性信息；pms_sku_sale_attr_value
            List<Attr> attrs = item.getAttr();
            List<SkuSaleAttrValueEntity> skuSaleAttrValueEntityList =
                attrs.stream()
                    .map(
                        attr -> {
                          SkuSaleAttrValueEntity skuSaleAttrValueEntity =
                              new SkuSaleAttrValueEntity();
                          BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
                          skuSaleAttrValueEntity.setSkuId(spuInfoEntity.getId());
                          return skuSaleAttrValueEntity;
                        })
                    .collect(Collectors.toList());
            skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntityList);
            // 6.4 sku的优惠、满减等信息：gulimall_sms
            // =》》sms_sku_ladder、sms_sku_full_reduction、sms_member_price
            SkuReductionTo skuReductionTo = new SkuReductionTo();
            BeanUtils.copyProperties(item, skuReductionTo);
            skuReductionTo.setSkuId(skuInfoEntity.getSkuId());
            if (skuReductionTo.getFullCount() > 0
                || skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) == 1) {
              R r1 = couponFeignService.saveSkuReduction(skuReductionTo);
              if (r1.getCode() != 0) {
                log.error("远程保存spu优惠信息失败");
              }
            }
          });
    }
  }

  @Override
  public PageUtils queryPageByCondition(Map<String, Object> params) {
    QueryWrapper<SpuInfoEntity> wapper = new QueryWrapper<>();
    String key = (String) params.get("key");
    if (!StringUtils.isEmpty(key)) {
      wapper.and(
          w -> {
            w.like("id", key).or().like("spu_name", key).or().like("spu_description", key);
          });
    }
    String status = (String) params.get("status");
    if (!StringUtils.isEmpty(status)) {
      wapper.eq("publish_status", status);
    }
    String brandId = (String) params.get("brandId");
    if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {
      wapper.eq("brand_id", brandId);
    }
    String catelogId = (String) params.get("catelogId");
    if (!StringUtils.isEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) {
      wapper.eq("catalog_id", catelogId);
    }
    IPage<SpuInfoEntity> page = this.page(new Query<SpuInfoEntity>().getPage(params), wapper);
    return new PageUtils(page);
  }
  /**
   * 商品上架
   *
   * @param spuId
   */
  @Transactional
  @Override
  public void up(Long spuId) {
    // 1、查出当前spuid对应的所有sku信息
    List<SkuInfoEntity> skus = skuInfoService.getSkusBySpuId(spuId);
    // TODO 4、查询当前可被检索的规格属性
    // 先获得所有的attr
    List<ProductAttrValueEntity> baseAttrs = productAttrValueService.baseAttrListForSpu(spuId);
    // 筛选出所有可以被检索的attr
    List<SkuEsModel.Attr> attrList = new ArrayList<>();
    List<Long> attrIds = new ArrayList<>();
    for (ProductAttrValueEntity baseAttr : baseAttrs) {
      // 根据attr_id查找所有attr
      AttrEntity attr = attrService.getById(baseAttr.getAttrId());
      if (attr.getSearchType() == 1) {
        SkuEsModel.Attr attr1 = new SkuEsModel.Attr();
        BeanUtils.copyProperties(attr, attr1);
        attrList.add(attr1);
        attrIds.add(attr1.getAttrId());
      }
    }
    // 收集包含可检索attr的skuid 用于下面查找库存
    Set<Long> idSet = new HashSet<>(attrIds);
    List<Long> collect1 =
        baseAttrs.stream()
            .filter(
                filte -> {
                  return idSet.contains(filte.getAttrId());
                })
            .map(ProductAttrValueEntity::getSpuId)
            .collect(Collectors.toList());
    // 查找库存
    Map<Long, Long> skusHasStock = null;
    try {
      skusHasStock = wareFeignService.getSkusHasStock(collect1);
    } catch (Exception e) {
      log.error("库存服务查询异常：{}", e.getMessage());
    }
    // 2、封装每个sku的信息到SkuEsModel中以便存储到es中
    Map<Long, Long> finalSkusHasStock = skusHasStock;
    List<SkuEsModel> collect =
        skus.stream()
            .map(
                item -> {
                  // 组装需要的数据
                  SkuEsModel skuEsModel = new SkuEsModel();
                  BeanUtils.copyProperties(item, skuEsModel);
                  /**
                   * skuPrice,skuImg,hasStock,hotScore brandName; brandImg; catalogName;
                   *
                   * <p>private Long attrId; private String attrName; private String attrValue;
                   */
                  skuEsModel.setSkuPrice(item.getPrice());
                  skuEsModel.setSkuImg(item.getSkuDefaultImg());
                  // TODO 1、发送远程查看是否还有库存
                  if (finalSkusHasStock != null) {
                    Long stock = finalSkusHasStock.get(item.getSkuId());
                    skuEsModel.setHasStock(stock != null && stock > 0);
                  } else {
                    skuEsModel.setHasStock(false);
                  }
                  // TODO 2、热度评分
                  skuEsModel.setHotScore(0L);
                  // TODO 3、查询分类和品牌
                  BrandEntity brand = brandService.getById(item.getBrandId());
                  if (brand.getName() != null) skuEsModel.setBrandName(brand.getName());
                  skuEsModel.setBrandImg(brand.getLogo());

                  CategoryEntity category = categoryService.getById(item.getCatalogId());
                  if (category.getName() != null) skuEsModel.setCatalogName(category.getName());

                  // 设置检索属性
                  skuEsModel.setAttrs(attrList);
                  return skuEsModel;
                })
            .collect(Collectors.toList());

    // TODO 5、将数据发送给es保存
    // 打印到控制台查看
    //    log.info("****************" + String.valueOf(collect) + "****************");
    R r = searchFeignService.productStatusUp(collect);
    if (r.getCode() == 0) {
      // 上架成功，修改spu状态
      this.baseMapper.updateSpuStatus(spuId, StatusEnum.SPU_UP.getCode());
    } else {
      // 上架失败
      // TODO 重复调用等问题    接口幂等性
    }
  }
}
